/**
 * @file resize-sensor.js.
 * @author liaoxuezhi@baidu.com
 */
/* eslint-disable */


class EventQueue {
  q = [];

  add(cb) {
    this.q.push(cb);
  }

  call(...args) {
    this.q.forEach((fn) => {
      fn(...args);
    });
  }
}

function getComputedStyle(element, prop) {
  if (element.currentStyle) {
    return element.currentStyle[prop];
  } else if (window.getComputedStyle) {
    return window.getComputedStyle(element, null).getPropertyValue(prop);
  } else {
    return element.style[prop];
  }
}

function attachResizeEvent(element, resized) {
  if (!element.resizedAttached) {
    element.resizedAttached = new EventQueue();
    element.resizedAttached.add(resized);
  } else if (element.resizedAttached) {
    element.resizedAttached.add(resized);
    return;
  }

  element.resizeSensor = document.createElement('div');
  element.resizeSensor.className = 'resize-sensor';
  let style = 'position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: scroll; z-index: -1; visibility: hidden;';
  let styleChild = 'position: absolute; left: 0; top: 0;';

  element.resizeSensor.style.cssText = style;
  element.resizeSensor.innerHTML =
    '<div class="resize-sensor-expand" style="' + style + '">' +
    '<div style="' + styleChild + '"></div>' +
    '</div>' +
    '<div class="resize-sensor-shrink" style="' + style + '">' +
    '<div style="' + styleChild + ' width: 200%; height: 200%"></div>' +
    '</div>';
  element.appendChild(element.resizeSensor);

  if (!{
      fixed: 1,
      absolute: 1
    }[getComputedStyle(element, 'position')]) {
    element.style.position = 'relative';
  }

  let expand = element.resizeSensor.childNodes[0];
  let expandChild = expand.childNodes[0];
  let shrink = element.resizeSensor.childNodes[1];
  let shrinkChild = shrink.childNodes[0];

  let lastWidth, lastHeight;

  let reset = function() {
    expandChild.style.width = expand.offsetWidth + 10 + 'px';
    expandChild.style.height = expand.offsetHeight + 10 + 'px';
    expand.scrollLeft = expand.scrollWidth;
    expand.scrollTop = expand.scrollHeight;
    shrink.scrollLeft = shrink.scrollWidth;
    shrink.scrollTop = shrink.scrollHeight;
    lastWidth = element.offsetWidth;
    lastHeight = element.offsetHeight;
  };

  reset();

  let changed = function() {
    if (element.resizedAttached) {
      element.resizedAttached.call();
    }
  };

  let addEvent = function(el, name, cb) {
    if (el.attachEvent) {
      el.attachEvent('on' + name, cb);
    } else {
      el.addEventListener(name, cb);
    }
  };

  let onScroll = function() {
    if (element.offsetWidth != lastWidth || element.offsetHeight != lastHeight) {
      changed();
    }
    reset();
  }

  addEvent(expand, 'scroll', onScroll);
  addEvent(shrink, 'scroll', onScroll);
}

function detach(element) {
  if (element.resizeSensor) {
    try {
      element.removeChild(element.resizeSensor);
    } catch (e) {};
    delete element.resizeSensor;
    delete element.resizedAttached;
  }
}

export function resizeSensor(element, callback) {
  attachResizeEvent(element, callback);
  let detached = false;

  return function() {
    if (detached) return;
    detached = true;
    detach(element);
  }
}